//=============================================================================
// Project  : NIPO Component Framework
// File    : SimpleInputPlugin.cs
// Author  : Bernhard Dieber (Bernhard.Dieber@uni-klu.ac.at)
// Copyright 2010 by Bernhard Dieber
// This code is published under the Microsoft Public License (Ms-PL).  A copy
// of the license should be distributed with the code.  It can also be found
// at the project website: http://NIPO.CodePlex.com.   This notice, the
// author's name, and all copyright notices must remain intact in all
// applications, documentation, and source files.
//=============================================================================
using System;
using System.Collections.Generic;
using NIPO.Data;
using NIPO.Plugins;
using NIPO.Util;
using System.IO;

namespace NIPOPlugins.Input
{
    public class SimpleInputPlugin : InputPlugin
    {
        #region Overrides of Plugin

        private SimpleInputConfiguration _configurationObject = new SimpleInputConfiguration();
        private FileStream _inputStream;

        /// <summary>
        /// Opportunity for a plugin to do pre-start initialization (e.g. resource allocation, event registration, ...)<br/>
        ///             This method is called immediately before the framework start (after checking that IsConfigured == <c>true</c>
        /// </summary>
        /// <remarks>
        /// Registration of non-standard events is supposed to happen here. If your plugin is supposed to catch events other than normal data events, this should be done here.
        /// </remarks>
        protected override void Initialize()
        {
            if (!string.IsNullOrEmpty(_configurationObject.Filename))
                _inputStream = File.OpenRead(_configurationObject.Filename);
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public override void Dispose()
        {

        }

        /// <summary>
        /// A plugin must provide a name
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        public override string Name
        {
            get { return "SimpleInputPlugin"; }
        }

        /// <summary>
        /// Every plugin must provide a description on what it does
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        public override string Description
        {
            get { return "A simple input plugin"; }
        }

        /// <summary>
        /// The ConfigurationObject is used to have a user configure a plugin.<br/>
        ///             Provide here a subclass of PluginConfiguration that defines the configuration values of your need
        /// </summary>
        /// <value>
        /// The configuration object.
        /// </value>
        public override PluginConfiguration ConfigurationObject
        {
            get { return _configurationObject; }
            set { _configurationObject = (SimpleInputConfiguration)value; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is configured.<br/>
        ///             "Configured" means that the plugin is ready to run and does not need any additional configuration information
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is configured; otherwise, <c>false</c>.
        /// </value>
        public override bool IsConfigured
        {
            get { return !string.IsNullOrEmpty(_configurationObject.Filename); }
        }

        /// <summary>
        /// Resets a PlugIn after a framework run. After this call the plugin must be runnable again
        /// </summary>
        public override void Reset()
        {
            if (_inputStream != null)
                _inputStream.Close();
        }

        #endregion

        #region IOutputChecker Members
        /// <summary>
        /// This method must return a set of possible outputs of this plugin
        /// </summary>
        public ICollection<DataTransferObject> GetSupportedOutput()
        {
            return new List<DataTransferObject> { new GenericDTO<byte[]>(null, "byte[]", 0, DateTime.Now) };
        }

        /// <summary>
        /// This method notifies the plugin what type of data it is expected to deliver.
        /// </summary>
        /// <remarks>
        /// This method may be called multiple times during the matching stage. 
        ///             The plugin should deliver all formats set in all calls.
        /// </remarks>
        /// <param eventName="expectedOutput">A set of sample data transfer objects. The plugin is expected to deliver all of those for each run.</param>
        /// <returns>
        /// <c>true</c> if the plugin is able to deliver all of the expected outputs, <c>false</c> if one or more formats cannot be provided.
        /// </returns>
        public bool DeliverOutput(DataTransferObject expectedOutput)
        {
            return expectedOutput is GenericDTO<byte[]>;
        }
        #endregion
        #region Overrides of InputPlugin
        /// <summary>
        /// The concrete implementation of this method provides the core input functionality of an InputPlugin. This method is always run in a dedicated Thread
        /// </summary>
        public override void Run()
        {
            try
            {
                Log.WriteDebug("Starting to read from file");
                while (!Abort)
                {
                    byte[] bytes = new byte[_configurationObject.ChunkSize];
                    int bytesRead = _inputStream.Read(bytes, 0, bytes.Length);
                    if (bytesRead > 0)
                        RaiseNewData(new GenericDTO<byte[]>(bytes, "byte[]", bytesRead, DateTime.Now));
                    else
                        break;
                }
            }
            finally
            {
                _inputStream.Close();
            }
            Log.WriteInfo("Finished reading file");
        }

        #endregion
    }
}